//
// Created by LONG on 2020/10/18.
//

#ifndef CSP_INCLUDE_UTILS_LIST_H_
#define CSP_INCLUDE_UTILS_LIST_H_

#include <stdint.h>
#include "commDef.h"

#ifdef __cplusplus
extern "C"
{
#endif

/******************************************************************************
  List : 双向循环链表
 ******************************************************************************/

typedef struct List
{
    struct List *next;
    struct List *prev;
} S_List;

void LIST_Init(S_List *self);
void LIST_Final(S_List *self);
void LIST_Prepend(S_List *self, S_List *node);
void LIST_Append(S_List *self, S_List *node);
void LIST_Remove(S_List *node);
int32_t LIST_Empty(const S_List *self);

#define LIST_FIRST_ENTRY(ptr, type, member) \
	CONTAINER_OF((ptr)->next, type, member)

#define LIST_LAST_ENTRY(ptr, type, member) \
	CONTAINER_OF((ptr)->prev, type, member)

/* 遍历链表 */
#define LIST_FOR_EACH(pos, head) \
    for (pos = (head)->next; pos != (head); pos = pos->next)

/* 安全遍历链表，支持在遍历过程中增删节点 */
#define LIST_FOR_EACH_SAFE(pos, head) \
    typeof(pos) EXP_AND_JOIN(__next_, __LINE__) = NULL;\
    for (pos = (head)->next, EXP_AND_JOIN(__next_, __LINE__) = pos->next; pos != (head); \
        pos = EXP_AND_JOIN(__next_, __LINE__), EXP_AND_JOIN(__next_, __LINE__) = pos->next)

/* 遍历链表实体 */
#define LIST_FOR_EACH_ENTRY(pos, head, member) \
    for (pos = CONTAINER_OF((head)->next, typeof(*pos), member);\
         &pos->member != (head);                    \
         pos = CONTAINER_OF((pos)->member.next, typeof(*pos), member))

/* 安全遍历链表实体，支持在遍历过程中增删节点 */
#define LIST_FOR_EACH_ENTRY_SAFE(pos, head, member) \
    typeof(pos) EXP_AND_JOIN(__next_, __LINE__) = NULL;\
    for (pos = CONTAINER_OF((head)->next, typeof(*pos), member),\
            EXP_AND_JOIN(__next_, __LINE__) = CONTAINER_OF((pos)->member.next, typeof(*pos), member);\
        &pos->member != (head);\
        pos = EXP_AND_JOIN(__next_, __LINE__), EXP_AND_JOIN(__next_, __LINE__) = CONTAINER_OF((EXP_AND_JOIN(__next_, __LINE__))->member.next, typeof(*pos), member))

#ifdef __cplusplus
}
#endif

#endif //CSP_INCLUDE_UTILS_LIST_H_
